package com.xjy.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.xjy.common.exception.CustomException;
import com.xjy.common.exception.UtilException;
import com.xjy.common.utils.PageUtils;
import com.xjy.common.core.page.PagePlus;
import com.xjy.common.core.page.TableDataInfo;
import com.xjy.system.domain.bo.*;
import com.xjy.system.domain.vo.SysCreditAdvanceVo;
import com.xjy.system.domain.vo.SysFundaccountVo;
import com.xjy.system.domain.vo.SysLoanVo;
import com.xjy.system.service.ISysCreditAdvanceService;
import com.xjy.system.service.ISysFundaccountService;
import com.xjy.system.service.ISysLoanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xjy.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjy.system.domain.SysFundaccountdetail;
import com.xjy.system.mapper.SysFundaccountdetailMapper;
import com.xjy.system.domain.vo.SysFundaccountdetailVo;
import com.xjy.system.service.ISysFundaccountdetailService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 资金账户变更明细信息Service业务层处理
 *
 * @author xjy
 * @date 2022-03-10
 */
@Service
public class SysFundaccountdetailServiceImpl extends ServicePlusImpl<SysFundaccountdetailMapper, SysFundaccountdetail> implements ISysFundaccountdetailService {

	@Autowired
	private ISysFundaccountService iSysFundaccountService;

	@Autowired
	private ISysLoanService iSysLoanService;
	@Autowired
	private ISysCreditAdvanceService iSysCreditAdvanceService;

	@Override
	public SysFundaccountdetailVo queryById(Long id) {
		return getVoById(id, SysFundaccountdetailVo.class);
	}

	@Override
	public TableDataInfo<SysFundaccountdetailVo> queryPageList(SysFundaccountdetailQueryBo bo) {
		PagePlus<SysFundaccountdetail, SysFundaccountdetailVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), SysFundaccountdetailVo.class);
		return PageUtils.buildDataInfo(result);
	}

	@Override
	public List<SysFundaccountdetailVo> queryList(SysFundaccountdetailQueryBo bo) {
		return listVo(buildQueryWrapper(bo), SysFundaccountdetailVo.class);
	}

	private LambdaQueryWrapper<SysFundaccountdetail> buildQueryWrapper(SysFundaccountdetailQueryBo bo) {
		Map<String, Object> params = bo.getParams();
		LambdaQueryWrapper<SysFundaccountdetail> lqw = Wrappers.lambdaQuery();
		lqw.eq(bo.getProjId() != null, SysFundaccountdetail::getProjId, bo.getProjId());
		lqw.eq(bo.getContractId() != null, SysFundaccountdetail::getContractId, bo.getContractId());
		lqw.eq(bo.getSettleProj() != null, SysFundaccountdetail::getSettleProj, bo.getSettleProj());
		lqw.eq(bo.getSubjectId() != null, SysFundaccountdetail::getSubjectId, bo.getSubjectId());
		lqw.eq(bo.getAccId() != null, SysFundaccountdetail::getAccId, bo.getAccId());
		lqw.eq(bo.getTransactionId() != null, SysFundaccountdetail::getTransactionId, bo.getTransactionId());
		lqw.eq(StrUtil.isNotBlank(bo.getSender()), SysFundaccountdetail::getSender, bo.getSender());
		lqw.eq(bo.getSenderId() != null, SysFundaccountdetail::getSenderId, bo.getSenderId());
		lqw.eq(StrUtil.isNotBlank(bo.getReceive()), SysFundaccountdetail::getReceive, bo.getReceive());
		lqw.eq(bo.getReceiveId() != null, SysFundaccountdetail::getReceiveId, bo.getReceiveId());
		lqw.eq(StrUtil.isNotBlank(bo.getManager()), SysFundaccountdetail::getManager, bo.getManager());
		lqw.eq(bo.getManagerId() != null, SysFundaccountdetail::getManagerId, bo.getManagerId());
		lqw.eq(bo.getCategory() != null, SysFundaccountdetail::getCategory, bo.getCategory());
		lqw.eq(bo.getTransactionDate() != null, SysFundaccountdetail::getTransactionDate, bo.getTransactionDate());
		lqw.eq(bo.getBeiginbalance() != null, SysFundaccountdetail::getBeiginbalance, bo.getBeiginbalance());
		lqw.eq(bo.getAmount() != null, SysFundaccountdetail::getAmount, bo.getAmount());
		lqw.eq(bo.getEndbalance() != null, SysFundaccountdetail::getEndbalance, bo.getEndbalance());
		lqw.eq(StrUtil.isNotBlank(bo.getRemarks()), SysFundaccountdetail::getRemarks, bo.getRemarks());
		lqw.orderByDesc(SysFundaccountdetail::getId);
		return lqw;
	}

	@Transactional
	@Override
	public synchronized Boolean insertByAddBo(SysFundaccountdetailAddBo bo) {
		bo.setAuditStatus(true);
		SysFundaccountdetail add = BeanUtil.toBean(bo, SysFundaccountdetail.class);
		Long projId = bo.getProjId();
		Long accId = bo.getAccId();
		//交易类型 0：收取押金、1：支付押金、2：预付账款、3：个人借款、4：支付报销、5：冲销借款，6：冲销预付，7：账户收款、8：其它不能为空
		Long transactionCategory = bo.getTransactionCategory();
		//发生金额
		BigDecimal amount = bo.getAmount();
		//0：收入(+)，1：支出(-)不能为空
		Long category = bo.getCategory();
		if (null == accId) {
			throw new CustomException("产生资金流水，账号ID不能为空！");
		}
		if (null == projId) {
			throw new CustomException("产生资金流水，项目ID不能为空！");
		}
		if (null == amount || amount.compareTo(new BigDecimal(0)) <= 0) {
			throw new CustomException("产生资金流水，交易金额必须大于0！");
		}
		if (null == category) {
			throw new CustomException("产生资金流水，收支类型不能为空！");
		}

		// 修改资金余额
		SysFundaccountQueryBo sysFundaccountQueryBo = new SysFundaccountQueryBo();
		sysFundaccountQueryBo.setProjId(projId);
		sysFundaccountQueryBo.setAccountId(accId);
		List<SysFundaccountVo> sysFundaccountVoList = iSysFundaccountService.queryList(sysFundaccountQueryBo);
		if (null == sysFundaccountVoList || sysFundaccountVoList.size() == 0) {
			throw new CustomException("产生资金流水，未查询到项目的资金账户！" + projId + "-" + accId);
		}
		SysFundaccountVo sysFundaccountVo = sysFundaccountVoList.get(0);
		BigDecimal accountLastbalance = sysFundaccountVo.getAccountLastbalance();

		//资金变更前余额
		add.setBeiginbalance(accountLastbalance);
		//交易类型 0：收取押金、1：支付押金、2：预付账款、3：个人借款、4：支付报销、5：冲销借款，6：冲销预付，7：账户收款、8：其它不能为空
		if (transactionCategory != 5L && transactionCategory != 6L) {
			//收
			if (category == 0) {
				accountLastbalance = accountLastbalance.add(amount);
			}
			//支出
			if (category == 1) {
				accountLastbalance = accountLastbalance.subtract(amount);
			}
			if (accountLastbalance.compareTo(new BigDecimal(0)) < 0) {
				throw new CustomException("资金余额不足！");
			}

			SysFundaccountEditBo sysFundaccountEditBo = new SysFundaccountEditBo();
			sysFundaccountEditBo.setProjId(projId);
			sysFundaccountEditBo.setAccountId(accId);
			sysFundaccountEditBo.setAccountLastbalance(accountLastbalance);

			iSysFundaccountService.updateAccountLastbalance(sysFundaccountEditBo);

		}
		//交易类型 0：收取押金、1：支付押金、2：预付账款、3：个人借款、4：支付报销、5：冲销借款，6：冲销预付，7：账户收款、8：其它不能为空
		if (transactionCategory == 5L) {
			//冲销预付款单
			SysLoanQueryBo sysLoanQueryBo = new SysLoanQueryBo();
			SysLoanEditBo sysLoanEditBo = new SysLoanEditBo();
			sysLoanQueryBo.setProjId(projId);
			sysLoanQueryBo.setLoanType(0);
			sysLoanQueryBo.setResultContractNo(bo.getTransactionId());
			List<SysLoanVo> list = iSysLoanService.queryList(sysLoanQueryBo);
			if(null == list || list.size() == 0 || list.size() >1){
				throw new CustomException("冲销借款时，查询借款数据异常！"+projId+"-"+bo.getTransactionId());
			}
			SysLoanVo sysLoanVo = list.get(0);
			BigDecimal advanceBalance = sysLoanVo.getBalance();
			Integer writeoffStatus = sysLoanVo.getWriteoffStatus();
			if(writeoffStatus == 1){
				throw new CustomException("当前借款款单已冲销！无需重复冲销"+bo.getTransactionId());
			}
			if(amount.compareTo(advanceBalance) >0){
				throw new CustomException("借款冲销！冲销金额大于余额！"+bo.getTransactionId());
			}
			if(amount.compareTo(advanceBalance) == 0){
				sysLoanEditBo.setWriteoffStatus(1);
				sysLoanEditBo.setBalance(new BigDecimal(0));
			}
			if(amount.compareTo(advanceBalance) < 0){
				sysLoanEditBo.setBalance(advanceBalance.subtract(amount));
			}
			sysLoanEditBo.setId(sysLoanVo.getId());

			iSysLoanService.updateByEditBo(sysLoanEditBo);
		}
		//交易类型 0：收取押金、1：支付押金、2：预付账款、3：个人借款、4：支付报销、5：冲销借款，6：冲销预付，7：账户收款、8：其它不能为空
		if (transactionCategory == 6L) {
			//冲销预付款单
			SysCreditAdvanceQueryBo sysCreditAdvanceQueryBo = new SysCreditAdvanceQueryBo();
			SysCreditAdvanceEditBo sysCreditAdvanceEditBo = new SysCreditAdvanceEditBo();
			sysCreditAdvanceQueryBo.setProjId(projId);
			sysCreditAdvanceQueryBo.setAdvanceType(0);
			sysCreditAdvanceQueryBo.setAdvanceNo(bo.getTransactionId());
			List<SysCreditAdvanceVo> list = iSysCreditAdvanceService.queryList(sysCreditAdvanceQueryBo);
			if(null == list || list.size() == 0 || list.size() >1){
				throw new CustomException("冲销预付时，查询预付款数据异常！"+projId+"-"+bo.getTransactionId());
			}
			SysCreditAdvanceVo sysCreditAdvanceVo = list.get(0);
			BigDecimal advanceBalance = sysCreditAdvanceVo.getAdvanceBalance();
			Integer writeoffStatus = sysCreditAdvanceVo.getWriteoffStatus();
			if(writeoffStatus == 1){
				throw new CustomException("当前预付款单已冲销！无需重复冲销"+bo.getTransactionId());
			}
			if(amount.compareTo(advanceBalance) >0){
				throw new CustomException("预付款冲销！冲销金额大于余额！"+bo.getTransactionId());
			}
			if(amount.compareTo(advanceBalance) == 0){
				sysCreditAdvanceEditBo.setWriteoffStatus(1);
				sysCreditAdvanceEditBo.setAdvanceBalance(new BigDecimal(0));
			}
			if(amount.compareTo(advanceBalance) < 0){
				sysCreditAdvanceEditBo.setAdvanceBalance(advanceBalance.subtract(amount));
			}
			sysCreditAdvanceEditBo.setId(sysCreditAdvanceVo.getId());
			iSysCreditAdvanceService.updateByEditBo(sysCreditAdvanceEditBo);
		}
		//资金变后前余额
		add.setEndbalance(accountLastbalance);

		add.setUpdateTime(new Date());
		return save(add);
	}

	@Override
	public Boolean updateByEditBo(SysFundaccountdetailEditBo bo) {
		SysFundaccountdetail update = BeanUtil.toBean(bo, SysFundaccountdetail.class);
		validEntityBeforeSave(update);
		return updateById(update);
	}


	/**
	 * 保存前的数据校验
	 *
	 * @param entity 实体类数据
	 */
	private void validEntityBeforeSave(SysFundaccountdetail entity) {
		//TODO 做一些数据校验,如唯一约束
	}

	@Override
	public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
		if (isValid) {
			//TODO 做一些业务上的校验,判断是否需要校验
		}
		return removeByIds(ids);
	}
}
